package com.liyunc.demo.custom.fileupload.client;

import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.Socket;

public class Client {

    JFrame jFrame;
    JTextArea filePath;
    JButton but_upload;
    JProgressBar progressBar;
    JButton but_stop;
    JButton but_start;

    Socket socket;
    private DataOutputStream dos;
    private DataInputStream dis;
    private RandomAccessFile rad;

    public volatile boolean flag = false;

    private static final int MIN_PROGRESS = 0;
    private static final int MAX_PROGRESS = 100;

    public Client() {
        jFrame = new JFrame("文件上传");
        jFrame.setSize(500, 120);
        jFrame.setLocationRelativeTo(null);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        filePath = new JTextArea();
        filePath.setSize(400, 10);

        but_upload = new JButton("上传文件");

        progressBar = new JProgressBar();

        but_stop = new JButton("停止");
        but_start = new JButton("开始");

        but_upload.addActionListener(uploadFileListener);
        but_start.addActionListener(startListener);
        but_stop.addActionListener(stopListener);

        // 创建第一个水平箱容器
        Box hBox1 = Box.createHorizontalBox();
        hBox1.add(filePath);
        hBox1.add(but_upload);

        Box hBox2 = Box.createHorizontalBox();
        hBox2.add(progressBar);

        Box hBox3 = Box.createHorizontalBox();
        hBox3.add(but_stop);
        hBox3.add(but_start);

        Box vBox = Box.createVerticalBox();
        vBox.add(hBox1);
        vBox.add(hBox2);
        vBox.add(hBox2);
        vBox.add(hBox3);

        jFrame.setContentPane(vBox);
        jFrame.setVisible(true);
    }

    private static void showFileOpenDialog(Component parent, JTextArea msgTextArea) {
        // 创建一个默认的文件选取器
        JFileChooser fileChooser = new JFileChooser();

        // 设置默认显示的文件夹为当前文件夹
        fileChooser.setCurrentDirectory(new File("."));

        // 设置文件选择的模式（只选文件、只选文件夹、文件和文件均可选）
        fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        // 设置是否允许多选
        fileChooser.setMultiSelectionEnabled(true);

        // 添加可用的文件过滤器（FileNameExtensionFilter 的第一个参数是描述, 后面是需要过滤的文件扩展名 可变参数）
        fileChooser.addChoosableFileFilter(
            new FileNameExtensionFilter("zip(*.zip, *.rar)", "zip", "rar"));
        // 设置默认使用的文件过滤器
        fileChooser.setFileFilter(
            new FileNameExtensionFilter("image(*.jpg, *.png, *.gif)", "jpg", "png", "gif"));

        // 打开文件选择框（线程将被阻塞, 直到选择框被关闭）
        int result = fileChooser.showOpenDialog(parent);

        if (result == JFileChooser.APPROVE_OPTION) {
            // 如果点击了"确定", 则获取选择的文件路径
            File file = fileChooser.getSelectedFile();

            msgTextArea.append(file.getAbsolutePath());
        }
    }

    private ActionListener uploadFileListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            progressBar.setValue(MIN_PROGRESS);
            showFileOpenDialog(jFrame, filePath);
        }
    };

    private ActionListener startListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            flag = true;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        socket = new Socket("localhost", 8080);
                    } catch (Exception ex) {
                        System.out.println("socket连接创建失败");
                    }
                    String path = filePath.getText();
                    System.out.println("file path = " + path);
                    if (!"".equals(path)) {
                        try {
                            dos = new DataOutputStream(socket.getOutputStream());
                            dis = new DataInputStream(socket.getInputStream());
                            dos.writeUTF("ok");

                            rad = new RandomAccessFile(path, "r");
                            File file = new File(path);

                            byte[] buf = new byte[1024];
                            dos.writeUTF(file.getName());
                            dos.flush();

                            String rsp = dis.readUTF();
                            if (rsp.equals("ok")) {
                                long size = dis.readLong();
                                dos.writeLong(rad.length());
                                dos.writeUTF("ok");
                                dos.flush();

                                long offset = size;

                                int barSize = (int) (rad.length() / 1024);
                                int barOffset = (int) (offset / 1024);

                                progressBar.setMinimum(MIN_PROGRESS);
                                progressBar.setMaximum(barSize);
                                progressBar.setValue(barOffset);
                                progressBar.setStringPainted(true);
                                progressBar.setPreferredSize(new Dimension(150, 20));
                                progressBar.setBorderPainted(true);
                                progressBar.setBackground(Color.pink);

                                int length;
                                if (offset < rad.length()) {
                                    rad.seek(offset);
                                    while ((length = rad.read(buf)) > 0 && flag) {
                                        dos.write(buf, 0, length);
                                        progressBar.setValue(++barOffset);
                                        dos.flush();
                                    }
                                }
                            }
                        } catch (Exception e) {
                            e.getStackTrace();
                        }
                    }
                }
            }).start();
        }
    };

    private ActionListener stopListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            flag = false;
            try {
                socket.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    };
}
